/*
 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 


#include <hi_stdlib.h>
#include <hisignalling_protocol.h>
#include <hi_uart.h>
#include <app_demo_uart.h>
#include <iot_uart.h>
#include <hi_gpio.h>
#include <hi_io.h>
#include "iot_gpio_ex.h"
#include "ohos_init.h"
#include "cmsis_os2.h"
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_watchdog.h"
#include "hi_io.h"
#include "iot_i2c.h"

#define IOT_GPIO_IDX_10 10 // for hispark_pegasus
UartDefConfig uartDefConfig = {0};
/*自己加的LED*/
#define LED_TEST_GPIO 9 // for hispark_pegasus

/*Hello world*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_i2c.h"
#include "iot_gpio.h"
#include "iot_errno.h"
#include "oled_ssd1306.h"
#define LED_INTERVAL_TIME_US 300000
#define AHT20_BAUDRATE (400 * 1000)
#define AHT20_I2C_IDX 0
hi_bool start;

/*舵机控制*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_time.h"
#define IOT_GPIO_SERVO 6
#define GPIO2 2
#define COUNT 10
#define TASK_STAK_SIZE    (1024*10)
/*门锁控制GPIO定义*/
#define IOT_GPIO_SERVO 6
#define IOT_GPIO_SERVO1 7
#define IOT_GPIO_SERVO2 8
#define GPIO2 2
#define COUNT 10
#define TASK_STAK_SIZE    (1024*10)
/*门锁控制初始化*/
void door1(void)
{
    /*GPIO7实验*/
    IoTGpioInit(IOT_GPIO_SERVO1);
    IoSetFunc(IOT_GPIO_SERVO1,0);
    IoTGpioSetDir(IOT_GPIO_SERVO1,IOT_GPIO_DIR_OUT);
    /*GPIO8实验LED2*/
    IoTGpioInit(IOT_GPIO_SERVO2);
    IoSetFunc(IOT_GPIO_SERVO2,0);
    IoTGpioSetDir(IOT_GPIO_SERVO2,IOT_GPIO_DIR_OUT);
}

void set_angle(unsigned int duty)
{
    unsigned int time = 20000;
    //IoTGpioSetDir(GPIO2, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(IOT_GPIO_SERVO, IOT_GPIO_VALUE1);
    hi_udelay(duty);
    IoTGpioSetOutputVal(IOT_GPIO_SERVO, IOT_GPIO_VALUE0);
    hi_udelay(time - duty);
}

/* Turn 45 degrees to the left of the steering gear
1、依据角度与脉冲的关系，设置高电平时间为1000微秒
2、不断地发送信号，控制舵机向左旋转45度
*/
void engine_turn_left_45(void)
{
    unsigned int angle = 1000;
    for (int i = 0; i < COUNT; i++) {
        set_angle(angle);
    }
}

/* Turn 90 degrees to the left of the steering gear
1、依据角度与脉冲的关系，设置高电平时间为500微秒
2、不断地发送信号，控制舵机向左旋转90度
*/
void engine_turn_left_90(void)
{
    unsigned int angle = 500;
    for (int i = 0; i < COUNT; i++) {
        set_angle(angle);
    }
}

/* Turn 45 degrees to the right of the steering gear
1、依据角度与脉冲的关系，设置高电平时间为2000微秒
2、不断地发送信号，控制舵机向右旋转45度
*/
void engine_turn_right_45(void)
{
    unsigned int angle = 2000;
    for (int i = 0; i < COUNT; i++) {
        set_angle(angle);
    }
}

/* Turn 90 degrees to the right of the steering gear
1、依据角度与脉冲的关系，设置高电平时间为2500微秒
2、不断地发送信号，控制舵机向右旋转90度
*/
void engine_turn_right_90(void)
{
    unsigned int angle = 2500;
    for (int i = 0; i < COUNT; i++) {
        set_angle(angle);
    }
}

/* The steering gear is centered
1、依据角度与脉冲的关系，设置高电平时间为1500微秒
2、不断地发送信号，控制舵机居中
*/
void regress_middle(void)
{
    unsigned int angle = 1500;
    for (int i = 0; i < COUNT; i++) {
        set_angle(angle);
    }
}

/* 任务实现 */
void RobotTask(void* parame)
{
    (void)parame;
    unsigned int time = 200;
    //printf("start test sg90\r\n");
    //engine_turn_left_45();
    //printf("Turn 45 degrees to the left of the steering gear\r\n");
    //osDelay(time);
    engine_turn_left_45();
    ("Turn 90 degrees to the left of the steering gear\r\n");
    osDelay(time);
    //regress_middle();
    //printf("The steering gear is centered");
    //osDelay(time);
    //engine_turn_right_45();
    //printf("Turn 45 degrees to the left of the steering gear\r\n");
    //osDelay(time);
    engine_turn_right_45();
    printf("Turn 90 degrees to the left of the steering gear\r\n");
    osDelay(time);
    //regress_middle();
    //printf("The steering gear is centered");
}


static void RobotDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "RobotTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = TASK_STAK_SIZE;
    attr.priority = osPriorityNormal;

    if (osThreadNew(RobotTask, NULL, &attr) == NULL) {
        printf("[RobotDemo] Falied to create RobotTask!\n");
    }
}

/*OLED控制*/
static void OledmentTask(const char *arg)
{
    (void)arg;
    OledInit();
    OledFillScreen(0);
    IoTI2cInit(AHT20_I2C_IDX, AHT20_BAUDRATE);

    OledShowString(20, 3, "Hello  World", 1); /* 屏幕第20列3行显示1行 */
}

static void OledDemo(void)
{
    osThreadAttr_t attr;
    attr.name = "OledmentTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4096; /* 任务大小4096 */
    attr.priority = osPriorityNormal;

    if (osThreadNew(OledmentTask, NULL, &attr) == NULL) {
        printf("[OledDemo] Falied to create OledmentTask!\n");
    }
}

static void Uart1GpioCOnfig(void)
{
#ifdef ROBOT_BOARD
    IoSetFunc(HI_IO_NAME_GPIO_5, IOT_IO_FUNC_GPIO_5_UART1_RXD);
    IoSetFunc(HI_IO_NAME_GPIO_6, IOT_IO_FUNC_GPIO_6_UART1_TXD);
    /* IOT_BOARD */
#elif defined (EXPANSION_BOARD)
    IoSetFunc(HI_IO_NAME_GPIO_0, IOT_IO_FUNC_GPIO_0_UART1_TXD);
    IoSetFunc(HI_IO_NAME_GPIO_1, IOT_IO_FUNC_GPIO_1_UART1_RXD);
#endif
}


int SetUartRecvFlag(UartRecvDef def)
{
    if (def == UART_RECV_TRUE) {
        uartDefConfig.g_uartReceiveFlag = HI_TRUE;
    } else {
        uartDefConfig.g_uartReceiveFlag = HI_FALSE;
    }
    
    return uartDefConfig.g_uartReceiveFlag;
}

int GetUartConfig(UartDefType type)
{
    int receive = 0;

    switch (type) {
        case UART_RECEIVE_FLAG:
            receive = uartDefConfig.g_uartReceiveFlag;
            break;
        case UART_RECVIVE_LEN:
            receive = uartDefConfig.g_uartLen;
            break;
        default:
            break;
    }
    return receive;
}

void ResetUartReceiveMsg(void)
{
    (void)memset_s(uartDefConfig.g_receiveUartBuff, sizeof(uartDefConfig.g_receiveUartBuff),
        0x0, sizeof(uartDefConfig.g_receiveUartBuff));
}

unsigned char *GetUartReceiveMsg(void)
{
    return uartDefConfig.g_receiveUartBuff;
}
/*串口通信结果控制外设响应*/
static hi_void *UartDemoTask(char *param)
{
    /*GPIO6初始化*/
    //IoTGpioInit(IOT_GPIO_SERVO);
    //IoSetFunc(IOT_GPIO_SERVO,0);
    //IoTGpioSetDir(IOT_GPIO_SERVO,IOT_GPIO_DIR_OUT);
    door1();
    
    OledInit();/*oled初始化*/
    OledFillScreen(0);
    //IoTI2cInit(AHT20_I2C_IDX, AHT20_BAUDRATE);
    /*LED初始化  &&(start==HI_FALSE)*/
    //IoTGpioInit(LED_TEST_GPIO);
    //IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT);
    start=HI_FALSE;
    hi_u8 uartBuff[UART_BUFF_SIZE] = {0};
    hi_unref_param(param);
    printf("Initialize uart demo successfully, please enter some datas via DEMO_UART_NUM port...\n");
    printf("Uart1 read data:aaa");
    Uart1GpioCOnfig();
    for (;;) {
        uartDefConfig.g_uartLen = IoTUartRead(DEMO_UART_NUM, uartBuff, UART_BUFF_SIZE);
        printf("=======================================\r\n");
        //printf("Uart1 read :%s", uartBuff[5]);
        if ((uartDefConfig.g_uartLen > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x55) && 
        (uartBuff[5] == 0x1) && (start==HI_FALSE)) {
            printf("face_home");
            //OledDemo();
            //RobotDemo();
            IoTGpioSetOutputVal(IOT_GPIO_SERVO1, IOT_GPIO_VALUE1);
            IoTGpioSetOutputVal(LED_TEST_GPIO, 1);
            usleep(LED_INTERVAL_TIME_US);
            OledFillScreen(0);
            OledShowString(20, 3, "face_home", 1);
            TaskMsleep(2000);
            IoTGpioSetOutputVal(IOT_GPIO_SERVO1, IOT_GPIO_VALUE0);
            start=HI_TRUE;
        }
        if ((uartDefConfig.g_uartLen > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x55) && (uartBuff[5] == 0x2)) {
            printf("other_people");
            //OledDemo();
            IoTGpioSetOutputVal(LED_TEST_GPIO, 0);
            usleep(LED_INTERVAL_TIME_US);
            OledFillScreen(0);
            OledShowString(20, 3, "other_people", 1);
            TaskMsleep(2000);
            start=HI_FALSE;
        }
        if ((uartDefConfig.g_uartLen > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x55) && (uartBuff[5] == 0x3)) {
            printf("back_groud");
            OledFillScreen(0);
            OledShowString(20, 3, "back_groud", 1);
            TaskMsleep(2000);
            start=HI_FALSE;
        }
        TaskMsleep(20); /* 20:sleep 20ms */
    }
    return HI_NULL;
}

/*
 * This demo simply shows how to read datas from UART2 port and then echo back.
 */
hi_void UartTransmit(hi_void)
{
    hi_u32 ret = 0;

    IotUartAttribute uartAttr = {
        .baudRate = 115200, /* baudRate: 115200 */
        .dataBits = 8, /* dataBits: 8bits */
        .stopBits = 1, /* stop bit */
        .parity = 0,
    };
    /* Initialize uart driver */
    ret = IoTUartInit(DEMO_UART_NUM, &uartAttr);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to init uart! Err code = %d\n", ret);
        return;
    }
    /* Create a task to handle uart communication */
    osThreadAttr_t attr = {0};
    attr.stack_size = UART_DEMO_TASK_STAK_SIZE;
    attr.priority = UART_DEMO_TASK_PRIORITY;
    attr.name = (hi_char*)"uart demo";
    if (osThreadNew((osThreadFunc_t)UartDemoTask, NULL, &attr) == NULL) {
        printf("Falied to create uart demo task!\n");
    }
}
SYS_RUN(UartTransmit);